home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Vertigo / Nub / Nub.c < prev    next >
C/C++ Source or Header  |  2000-06-23  |  7KB  |  320 lines

  1. #define DISABLE_LOCAL_CALLTRACE        1        // Set to 1 to disable Call Traces for this file.
  2. #define DISABLE_LOCAL_DEBUG            0        // Set to 1 to disable all debugging for this file.
  3. #include "DebugUtils.h"
  4.  
  5. #include <Errors.h>
  6. #include <Gestalt.h>
  7. #include "ContextUtils.h"
  8. #include "Nub.h"
  9. #include "Patches.h"
  10. #include "PatchHarness.h"
  11. #include "Port.h"
  12. #include "ProcInfo.h"
  13. #include "Version.h"
  14.  
  15.  
  16.  
  17.  
  18.  
  19. #ifdef __cplusplus
  20. extern "C" {
  21. #endif
  22.  
  23. extern void    __InitCode__(void);
  24. extern void    __destroy_global_chain(void);
  25.  
  26. #if APPBUILD
  27.     OSStatus NubMain(Handle code);
  28. #else
  29.     pascal OSStatus main(Handle code);
  30. #endif
  31.  
  32. static OSStatus LoadNub(Handle code);
  33. static pascal OSStatus UnloadNub(Handle *code);
  34. static Boolean isPressed(UInt8 keyCode);
  35.  
  36. #if GENERATING68K && !GENERATINGCFM && __A5__
  37.     void RememberA5(void);
  38. #endif
  39.  
  40. #ifdef __cplusplus
  41. }
  42. #endif
  43.  
  44.  
  45.  
  46.  
  47.  
  48. #if GENERATINGPOWERPC
  49.     ProcInfoType                            __procinfo = uppNubLoadProcInfo;
  50.     static RoutineDescriptor                gUnloadNubRD = BUILD_ROUTINE_DESCRIPTOR(uppNubUnloadProcInfo,UnloadNub);
  51.     static RoutineDescriptor                *gUnloadNubUPP = (RoutineDescriptor*)&gUnloadNubRD;
  52. #else
  53.     static NubUnloadUPP                        gUnloadNubUPP = UnloadNub;
  54. #endif
  55.  
  56.  
  57. NubInfo                                        *gInfo = NULL;
  58. static Handle                                gCode = NULL;
  59. static UInt32                                gAbortLoad = 0;
  60. static Boolean                                gBootInstall = false;
  61. static Boolean                                gDestructOnUnload = false;
  62.  
  63.  
  64.  
  65.  
  66.  
  67. #if APPBUILD
  68.     OSStatus NubMain(Handle code)
  69.     #pragma mark NubMain
  70. #else
  71.     pascal OSStatus main(Handle code)
  72. #endif
  73. {
  74. #if !APPBUILD
  75.     GlobalContext    globals;
  76. #endif
  77.     OSStatus        err;
  78.     
  79.     
  80.     #if DEBUG
  81.         // Check for CapsLock.
  82.         if (isPressed(0x39))
  83.         {
  84.             DebugStr("\pNub abort checkpoint");
  85.             if (gAbortLoad)
  86.             {
  87.                 dprintf(kDConPrefix "LoadNub aborted\n");
  88.                 return -1;
  89.             }
  90.         }
  91.     #endif
  92.     
  93.     // Save application global A5 world.
  94.     #if GENERATING68K && !GENERATINGCFM && __A5__
  95.         RememberA5();
  96.     #endif
  97.     
  98.     // 68K code resources need to construct their own static C++ data objects (A4 must be
  99.     // setup).  We only need to do this for 68K because it'll be automagically constructed
  100.     // by the CFM init routine for a PowerPC code resource.
  101.     #if !GENERATINGPOWERPC && !APPBUILD
  102.         __InitCode__();
  103.     #endif
  104.     
  105.     // Install the Nub, if this fails we just forward the error.
  106.     // Our caller has already detached us and if we return an error it
  107.     // is responsible for unloading us, otherwise we will stick around.
  108.     err = LoadNub(code);
  109.     if (err != noErr)    
  110.     {
  111.         dprintf(kDConPrefix "LoadNub failed: %ld\n",err);
  112.         // Code resources need to destruct their own static C++ data objects (A4 must be
  113.         // setup for 68K).  We must do this PowerPC code resources too, as CFM termination
  114.         // routines won't be invoked when a code resource is unloaded.
  115.         #if !APPBUILD
  116.             __destroy_global_chain();
  117.         #endif
  118.     }
  119.     else
  120.         gDestructOnUnload = true;
  121.     
  122.     return err;
  123. }
  124.  
  125.  
  126.  
  127.  
  128.  
  129. OSStatus LoadNub(Handle code)
  130. {
  131.     THzContext    zone(SystemZone());
  132.     NubInfo        *info;
  133.     SInt32        result;
  134.     OSStatus    err;
  135.     
  136.     
  137.     // Check Gestalt to determine install/reinstall.
  138.     err = Gestalt(kNubSelector,(SInt32*)&info);
  139.     if (err != noErr)
  140.         info = NULL;
  141.     
  142.     // The INIT must be loaded first to bootstrap the debugging application version,
  143.     // otherwise we won't be able to install any patches.
  144.     #if APPBUILD
  145.         if ((err != noErr) || (info == NULL))
  146.             return notOpenErr;
  147.     #endif
  148.     
  149.     // Check for Nub already being present and loaded.
  150.     if ((err == noErr) && info && (info->signature == kNubSignature))
  151.         return opWrErr;
  152.     
  153.     // If the Gestalt selector didn't exist, or the permanent data structures haven't
  154.     // been setup (which means we haven't patched anything yet), this is an install.
  155.     if ((err != noErr) || (info == NULL))
  156.     {
  157.         if (info == NULL)
  158.         {
  159.             // Allocate system exposed permanent data structures.
  160.             info = (NubInfo*)NewPtrSysClear(sizeof(NubInfo));
  161.             if (info == NULL)
  162.             {
  163.                 err = MemError();
  164.                 dprintf(kDConPrefix "Couldn't allocate NubInfo: %ld\n",err);
  165.                 return err;
  166.             }
  167.         }
  168.         
  169.         if (err != noErr)
  170.         {
  171.             // Install system wide patch harness.
  172.             err = InstallPatchHarness(&info->patchList);
  173.             if (err != noErr)
  174.             {
  175.                 dprintf(kDConPrefix "InstallPatchHarness failed: %ld\n",err);
  176.                 DisposePtr((Ptr)info);
  177.                 return err;
  178.             }
  179.         }
  180.         
  181.         // Setup pointer to NubInfo as Gestalt selector result.
  182.         err = InstallPatch(info->patchList,'GSEL',(UniversalProcPtr)info);
  183.         if (err != noErr)
  184.         {
  185.             dprintf(kDConPrefix "Couldn't install '.4%s' Gestalt selector: %ld\n",err);
  186.             DisposePtr((Ptr)info);
  187.             return err;
  188.         }
  189.         
  190.         // Set boot time flag.
  191.         gBootInstall = true;
  192.     }
  193.     
  194.     // Setup globals.
  195.     gCode = code;
  196.     gInfo = info;
  197.     
  198.     // Setup NubInfo record.
  199.     gInfo->signature = kNubSignature;
  200.     *(UInt32*)&gInfo->version = kNubVersion;
  201.     *(UInt32*)&gInfo->compatible = kNubCompatible;
  202.     gInfo->unloadProc = gUnloadNubUPP;
  203.     
  204.     // Make it go....
  205.     #if APPBUILD
  206.         err = InitializePorts();
  207.         if (err != noErr)
  208.             goto error;
  209.         
  210.         InitializePatches();
  211.     #endif
  212.     
  213.     #if DEBUG
  214.     {
  215.         UInt32    vers = kNubVersion;
  216.         char    text[32];
  217.         
  218.         dprintf(kDConPrefix "Vertigo %s installed\n",NumVersionToCString(text,(NumVersion*)&vers));
  219.     }
  220.     #endif
  221.     
  222.     return noErr;
  223.     
  224. error:
  225.     #if APPBUILD
  226.         FinalizePatches();
  227.         FinalizePorts();
  228.     #endif
  229.     
  230.     gInfo->signature = 0;
  231.     gInfo->unloadProc = NULL;
  232.     return err;
  233. }
  234.  
  235.  
  236.  
  237.  
  238.  
  239. pascal OSStatus UnloadNub(Handle *code)
  240. {
  241.     GlobalContext    globals;
  242.     THzContext        zone(SystemZone());
  243.     PatchDesc        *patch;
  244.     
  245.     
  246.     // Make it stop...
  247.     #if APPBUILD
  248.         FinalizePatches();
  249.         FinalizePorts();
  250.     #endif
  251.     
  252.     // Remove all patches.
  253.     patch = gInfo->patchList;
  254.     while(patch != NULL)
  255.     {
  256.         // Don't remove our special GestaltSelector patch.
  257.         if ((patch->type != 'GSEL') && patch->remove)
  258.             CallPatchRemoveProc(patch->remove,patch);
  259.         
  260.         patch = patch->next;
  261.     }
  262.     
  263.     // Clear NubInfo record.
  264.     gInfo->signature = 0;
  265.     gInfo->unloadProc = NULL;
  266.     
  267.     // Caller must dispose.
  268.     #if APPBUILD
  269.         *code = NULL;
  270.     #else
  271.         *code = gCode;
  272.     #endif
  273.     
  274.     if (gDestructOnUnload)
  275.     {
  276.         // Code resources need to destruct their own static C++ data objects (A4 must be
  277.         // setup for 68K).  We must do this PowerPC code resources too, as CFM termination
  278.         // routines won't be invoked when a code resource is unloaded.
  279.         #if !APPBUILD
  280.             __destroy_global_chain();
  281.         #endif
  282.         gDestructOnUnload = false;
  283.     }
  284.     
  285.     return noErr;
  286. }
  287.  
  288.  
  289.  
  290.  
  291.  
  292. Boolean isPressed(UInt8 keyCode)
  293. {
  294.     UInt8    km[16];
  295.     
  296.     
  297.     GetKeys((UInt32*)&km[0]);
  298.     return ((km[keyCode >> 3] >> (keyCode & 7)) & 1);
  299. }
  300.  
  301.  
  302.  
  303.  
  304.  
  305. #if GENERATING68K && !GENERATINGCFM && __A5__
  306.     asm void RememberA5(void)
  307.     {
  308.         LEA            @A5Storage,A0
  309.         MOVE.L        A5,(A0)
  310.         RTS
  311.         
  312.     entry GetCurrentA5
  313.         MOVE.L        @A5Storage,D0
  314.         RTS
  315.         
  316.     @A5Storage:
  317.         DC.L        0x00000000
  318.     }
  319. #endif
  320.